package me.qingy.programmatic;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.Arrays;

/**
 * 扫描一次就行，以及 isAlpha() toLower() 函数实现练习
 *
 * @author qingy
 * @since 2021/8/19
 */
public class ValidPalindrome {

    /**
     * 扫描一次
     */
    public boolean isPalindrome1(String s) {
        int i = 0;
        int j = s.length() - 1;

        while (i < j){
            if (!isAlpha(s.charAt(i))){ // 不是字母或数字，指针 i 右移
                i++;
                continue;
            }
            if (!isAlpha(s.charAt(j))){ // 不是字母或数字，指针 j 左移
                j--;
                continue;
            }
            if (toLower(s.charAt(i)) != toLower(s.charAt(j))) {
                return false;
            } else {
                i++;
                j--;
            }
        }

        return true;
    }

    /**
     * 扫描两次
     */
    public boolean isPalindrome2(String s) {
        char[] chars = s.toCharArray();
        int k = 0;
        // 去除字母与数字外的字符，并且大写转小写
        for (char c : chars) {
            if (isAlpha(c)) {
                if (c >= 'A' && c <= 'Z') {
                    chars[k] = toLower(c);
                } else {
                    chars[k] = c;
                }
                k++;
            }
        }

        char[] array = Arrays.copyOf(chars, k);

        // 是否回文
        int n = array.length - 1;
        for (int i = 0; i < array.length / 2; i++) {
            if (array[i] != array[n]) {
                return false;
            }
            n--;
        }
        return true;
    }

    /**
     * 数字48~57 大写65~90 小写97~122
     */
    public boolean isAlpha(char c) {
        if (c >= 'a' && c <= 'z') return true;
        if (c >= 'A' && c <= 'Z') return true;
        if (c >= '0' && c <= '9') return true;
        return false;
    }

    /**
     * 转小写
     */
    public char toLower(char c) {
        if (c >= 'a' && c <= 'z') return c;
        if (c >= '0' && c <= '9') return c;
        return (char) (c + 32);
    }

    @Test
    public void testIsPalindrome() {
        Assertions.assertTrue(isPalindrome1("A man, a plan, a canal: Panama"));
        Assertions.assertFalse(isPalindrome1("race a car"));
    }
}
